﻿#ifndef _CELL_TIMER_HPP_
#define _CELL_TIMER_HPP_

#include <set>
#include <algorithm>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif


#ifdef WIN32
static unsigned int
get_cur_ms() {
	return GetTickCount();
}
#else
static unsigned int
get_cur_ms() {
	struct timeval tv;
	struct timezone tz;
	gettimeofday(&tv, &tz);

	return ((tv.tv_usec / 1000) + tv.tv_sec * 1000);
}
#endif

class CELLTimer
{
public:
	typedef void(*time_callback)(void*);
	//定时器的类型
	class Timer
	{
		friend class CELLTimer;
		time_callback cb; // Timer回掉函数的指针;
		void* udata; // 用户要在Timer触发后传给回掉函数的数据指针;

		unsigned int duration; // 触发的时间间隔
		unsigned int end_time_stamp; // 结束的时间戳,毫秒;
		int repeat; // 重复的次数，-1,表示一直调用;
	};
public:
	CELLTimer()
	{

	}
	~CELLTimer()
	{
		auto begin = _timer_list.begin();
		auto end = _timer_list.end();
		for (; begin != end; ++begin)
		{
			delete begin->second;
		}
		_timer_list.clear();
	}

	//获得multimap距现在最快发生的时间事件的时间，单位(毫秒)
	unsigned int getTime()
	{
		if (_timer_list.size() > 0)
		{
			auto time = _timer_list.begin()->first - get_cur_ms();
			return time > 0 ? time : 0;
		}
		return 0;
	}

	//注册定时事件
	unsigned int 
	register_time_event(time_callback cb, void *ctx, unsigned int after_sec, int repeat = 1)
	{
		Timer* timer = new Timer();
		timer->cb = cb;
		timer->duration = (unsigned int)(after_sec * 1000);
		timer->end_time_stamp = get_cur_ms() + timer->duration;
		timer->udata = ctx;
		timer->repeat = repeat;
		auto pair = std::make_pair(timer->end_time_stamp, timer);
		_timer_list.insert(pair);
		return timer->end_time_stamp;
	}

	//取消注册定时事件
	void 
	unregister_time_event(unsigned int timerid)
	{
		if (_cur_running_timer == timerid)
		{// 阻止触发自己的时候删除自己
			return;
		}
		auto iter = _timer_list.find(timerid);
		if (iter != _timer_list.end())
		{ // 找到了这个定时器
			delete iter->second;
			_timer_list.erase(iter);
		}
	}

	//更新定时事件的时间
	unsigned int
	update_time_event(unsigned int timerid, unsigned int after_sec, int repeat = 1)
	{
		auto iter = _timer_list.find(timerid);
		unsigned returnTimerId = -1;
		if (iter != _timer_list.end())
		{ // 找到了这个定时器
			returnTimerId = register_time_event(iter->second->cb, iter->second->udata, after_sec, repeat);
			delete iter->second;
			_timer_list.erase(iter);
		}
		return returnTimerId;
	}

	void 
	process_timer()
	{
		unsigned int cur_time = get_cur_ms();
		auto begin = _timer_list.begin();
		auto end = _timer_list.end();
		while (begin != end)
		{
			_cur_running_timer = begin->first;
			if (_cur_running_timer <= cur_time)
			{
				begin->second->cb(begin->second->udata);
				if (begin->second->repeat > 0)
				{// 表示是有限的触发次数
					--begin->second->repeat;
					if (begin->second->repeat == 0)
					{// 该定时器已经失效
						auto oldIter = begin++;
						delete oldIter->second;
						_timer_list.erase(oldIter);
						continue;
					}
				}
				update_time_event(begin->first, begin->second->duration / 1000, begin->second->repeat);
			}
			break;
		}
		_cur_running_timer = 0;
	}

private:
	//存放键为时间值为回调函数的容器
	//键是毫秒
	std::multimap<unsigned int, Timer*> _timer_list;
	unsigned int _cur_running_timer = 0;
};

#endif //_CELL_TIMER_HPP_
